---
slug: /cookbook
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

# Cookbook

## Filesystem

### Mount or copy a directory or remote repository to a container

The following Dagger Function accepts a `Directory` argument, which could reference either a directory from the local filesystem or from a [remote Git repository](../api/remote-repositories.mdx). It mounts the specified directory to the `/src` path in a container and returns the modified container.

:::note
When working with private Git repositories, ensure that [SSH authentication is properly configured](../api/remote-repositories.mdx#ssh-authentication) on your Dagger host.
:::


<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/mount-dir/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/mount-dir/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/mount-dir/typescript/index.ts
```

</TabItem>

<TabItem value="php" label="PHP">

```php file=./snippets/mount-dir/php/src/MyModule.php
```

</TabItem>
</Tabs>

An alternative option is to copy the target directory in the container. The difference between these two approaches is that mounts only take effect within your workflow invocation; they are not copied to, or included, in the final image. In addition, any changes to mounted files and/or directories will only be reflected in the target directory and not in the mount sources.

:::tip
Besides helping with the final image size, mounts are more performant and resource-efficient. The rule of thumb should be to always use mounts where possible.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-dir/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-dir/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-dir/typescript/index.ts
```

</TabItem>

<TabItem value="php" label="PHP">

```php file=./snippets/copy-dir/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Examples

- Mount the `/myapp` host directory to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-directory ./myapp/'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-directory ./myapp/
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call mount-directory --source=./myapp/
    ```
    </TabItem>
    </Tabs>

- Mount the public `dagger/dagger` GitHub repository to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-directory https://github.com/dagger/dagger#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-directory https://github.com/dagger/dagger#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call mount-directory --source=https://github.com/dagger/dagger#main
    ```
    </TabItem>
    </Tabs>

- Mount the private `user/foo` GitHub repository to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-directory ssh://git@github.com/user/foo#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-directory ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call mount-directory --source=ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    </Tabs>

- Mount the public `dagger/dagger` GitHub repository to `/src` in the container and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-directory https://github.com/dagger/dagger#main | directory /src | entries'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-directory https://github.com/dagger/dagger#main | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      mount-directory --source=https://github.com/dagger/dagger#main \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

- Copy the `/myapp` host directory to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory ./myapp/'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory ./myapp/
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-directory --source=./myapp/
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory https://github.com/dagger/dagger#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory https://github.com/dagger/dagger#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-directory --source=https://github.com/dagger/dagger#main
    ```
    </TabItem>
    </Tabs>

- Copy the private `user/foo` GitHub repository to `/src` in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory ssh://git@github.com/user/foo#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-directory --source=ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory https://github.com/dagger/dagger#main | directory /src | entries'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory https://github.com/dagger/dagger#main | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-directory --source=https://github.com/dagger/dagger#main \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

### Modify a copied directory or remote repository in a container

The following Dagger Function accepts a `Directory` argument, which could reference either a directory from the local filesystem or from a [remote Git repository](../api/arguments.mdx#remote-repositories). It copies the specified directory to the `/src` path in a container, adds a file to it, and returns the modified container.

:::note
When a host directory or file is copied or mounted to a container's filesystem, modifications made to it in the container do not automatically transfer back to the host. Data flows only one way between Dagger operations, because they are connected in a DAG. To transfer modifications back to the local host, you must explicitly export the directory or file back to the host filesystem.
:::

:::note
When working with private Git repositories, ensure that [SSH authentication is properly configured](../api/remote-repositories.mdx#ssh-authentication) on your Dagger host.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-modify-dir/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-modify-dir/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-modify-dir/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/copy-modify-dir/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Examples

- Copy the `/myapp` host directory to `/src` in the container, add a file to it, and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-and-modify-directory ./myapp/'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-and-modify-directory ./myapp/
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-and-modify-directory --source=./myapp/
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container, add a file to it, and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-and-modify-directory github.com/dagger/dagger#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-and-modify-directory github.com/dagger/dagger#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-and-modify-directory --source=github.com/dagger/dagger#main
    ```
    </TabItem>
    </Tabs>

- Copy the private `user/foo` GitHub repository to `/src` in the container, add a file to it, and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-and-modify-directory ssh://git@github.com/user/foo#main'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-and-modify-directory ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-and-modify-directory --source=ssh://git@github.com/user/foo#main
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container, add a file to it, and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-and-modify-directory https://github.com/dagger/dagger#main | directory /src | entries'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-and-modify-directory https://github.com/dagger/dagger#main | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-and-modify-directory --source=https://github.com/dagger/dagger#main \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

### Clone a remote Git repository into a container

The following Dagger Function accepts a Git repository URL and a Git reference. It copies the repository at the specified reference to the `/src` path in a container and returns the modified container.

:::note
For examples of SSH-based cloning, including private or public Git repositories with an SSH reference format, select the `SSH` tabs below. This approach requires explicitly forwarding the host `SSH_AUTH_SOCK` to the Dagger Function. Learn more about this in Dagger's [security model](../features/security.mdx).
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/clone-git-repository/go/main.go
```

</TabItem>
<TabItem value="Go (SSH)">

```go file=./snippets/clone-git-repository-ssh/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/clone-git-repository/python/main.py
```

</TabItem>
<TabItem value="Python (SSH)">

```python file=./snippets/clone-git-repository-ssh/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/clone-git-repository/typescript/index.ts
```

</TabItem>
<TabItem value="TypeScript (SSH)">

```typescript file=./snippets/clone-git-repository-ssh/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/clone-git-repository/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Examples

- Clone the public `dagger/dagger` GitHub repository to `/src` in the container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'clone https://github.com/dagger/dagger 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    clone https://github.com/dagger/dagger 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call clone --repository=https://github.com/dagger/dagger --ref=196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5
    ```
    </TabItem>
    </Tabs>

- Clone the public `dagger/dagger` GitHub repository at reference `196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5` to `/src` in the container and open an interactive terminal to inspect the container filesystem:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    clone https://github.com/dagger/dagger 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 |
      terminal
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    clone https://github.com/dagger/dagger 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 | terminal
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      clone --repository=https://github.com/dagger/dagger --ref=196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 \
      terminal
    ```
    </TabItem>
    </Tabs>

- Clone over SSH with socket forwarding:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    clone-with-ssh git@github.com:dagger/dagger.git 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 $SSH_AUTH_SOCK |
      terminal
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    clone-with-ssh git@github.com:dagger/dagger.git 196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 $SSH_AUTH_SOCK | terminal
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      clone-with-ssh --repository=git@github.com:dagger/dagger.git --ref=196f232a4d6b2d1d3db5f5e040cf20b6a76a76c5 --sock=$SSH_AUTH_SOCK \
      terminal
    ```
    </TabItem>
    </Tabs>

### Mount or copy a local or remote file to a container

The following Dagger Function accepts a `File` argument, which could reference either a file from the local filesystem or from a [remote Git repository](../api/arguments.mdx#remote-repositories). It mounts the specified file to a container in the `/src/` directory and returns the modified container.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/mount-file/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/mount-file/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/mount-file/typescript/index.ts
```

</TabItem>
</Tabs>

An alternative option is to copy the target file to the container. The difference between these two approaches is that mounts only take effect within your workflow invocation; they are not copied to, or included, in the final image. In addition, any changes to mounted files and/or directories will only be reflected in the target directory and not in the mount sources.

:::tip
Besides helping with the final image size, mounts are more performant and resource-efficient. The rule of thumb should be to always use mounts where possible.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-file/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-file/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-file/typescript/index.ts
```

</TabItem>
</Tabs>


#### Example

-  Mount the `/home/admin/archives.zip` file on the host to the `/src` directory in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-file /home/admin/archives.zip'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-file /home/admin/archives.zip
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call mount-file --f=/home/admin/archives.zip
    ```
    </TabItem>
    </Tabs>

-  Mount the `README.md` file from the public `dagger/dagger` GitHub repository to the `/src` directory in the container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'mount-file https://github.com/dagger/dagger.git#main:README.md'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-file https://github.com/dagger/dagger.git#main:README.md
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call mount-file --f=https://github.com/dagger/dagger.git#main:README.md
    ```
    </TabItem>
    </Tabs>

-  Mount the `README.md` file from the public `dagger/dagger` GitHub repository to the `/src` directory in the container and display its contents:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    mount-file https://github.com/dagger/dagger.git#main:README.md |
      file /src/README.md |
      contents
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    mount-file https://github.com/dagger/dagger.git#main:README.md | file /src/README.md | contents
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      mount-file --f=https://github.com/dagger/dagger.git#main:README.md \
      file --path=/src/README.md \
      contents
    ```
    </TabItem>
    </Tabs>

- Copy the `/home/admin/archives.zip` file on the host to the `/src` directory in the container and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-file /home/admin/archives.zip'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-file /home/admin/archives.zip
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-file --f=/home/admin/archives.zip
    ```
    </TabItem>
    </Tabs>

- Copy the `/home/admin/archives.zip` file on the host to the `/src` directory in the container and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-file /home/admin/archives.zip | directory /src | entries'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-file /home/admin/archives.zip | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-file --f=/home/admin/archives.zip \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

-  Copy the `README.md` file from the public `dagger/dagger` GitHub repository to the `/src` directory in the container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-file https://github.com/dagger/dagger.git#main:README.md'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-file https://github.com/dagger/dagger.git#main:README.md
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-file --f=https://github.com/dagger/dagger.git#main:README.md
    ```
    </TabItem>
    </Tabs>

-  Copy the `README.md` file from the public `dagger/dagger` GitHub repository to the `/src` directory in the container and display its contents:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    copy-file https://github.com/dagger/dagger.git#main:README.md |
      file /src/README.md |
      contents
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-file https://github.com/dagger/dagger.git#main:README.md | file /src/README.md | contents
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-file --f=https://github.com/dagger/dagger.git#main:README.md \
      file --path=/src/README.md \
      contents
    ```
    </TabItem>
    </Tabs>

### Copy a subset of a directory or remote repository to a container using filters specified at run-time

The following Dagger Function accepts a `Directory` argument, which could reference either a directory from the local filesystem or a [remote Git repository](../api/arguments.mdx#remote-repositories). It copies the specified directory to the `/src` path in a container, using a filter pattern specified at call-time to exclude specified sub-directories and files, and returns the modified container.

:::note
When working with private Git repositories, ensure that [SSH authentication is properly configured](../api/remote-repositories.mdx#ssh-authentication) on your Dagger host.
:::

:::note
This is an example of [post-call filtering](../api/fs-filters.mdx#post-call-filtering) with [directory filters](../api/fs-filters.mdx).
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-filter-dir-post/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-filter-dir-post/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-filter-dir-post/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Copy the current host directory to `/src` in the container, excluding all sub-directories and files starting with `dagger`, and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory-with-exclusions . --exclude=dagger*'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory-with-exclusions . --exclude=dagger*
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-directory-with-exclusions --source=. --exclude=dagger*
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container, excluding all Markdown files, and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    copy-directory-with-exclusions https://github.com/dagger/dagger#main --exclude=*.md |
      directory /src |
      entries
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory-with-exclusions https://github.com/dagger/dagger#main --exclude=*.md | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-directory-with-exclusions --source=https://github.com/dagger/dagger#main --exclude=*.md \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

- Copy the private `user/foo` GitHub repository to `/src` in the container, excluding all Markdown files, and list the contents of the directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    copy-directory-with-exclusions ssh://git@github.com/user/foo#main --exclude=*.md |
      directory /src |
      entries
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory-with-exclusions ssh://git@github.com/user/foo#main --exclude=*.md | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-directory-with-exclusions --source=ssh://git@github.com/user/foo#main --exclude=*.md \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

### Request a file over HTTP/HTTPS and save it in a container

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/read-file-http/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/read-file-http/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/read-file-http/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

-  Request the `README.md` file from the public `dagger/dagger` GitHub repository over HTTPS, save it as `/src/myfile` in the container, and return the container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'read-file-http https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    read-file-http https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call read-file-http --url=https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md
    ```
    </TabItem>
    </Tabs>

-  Request the `README.md` file from the public `dagger/dagger` GitHub repository over HTTPS, save it as `/src/myfile` in the container, and display its contents:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger <<EOF
    read-file-http https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md |
      file /src/myfile |
      contents
    EOF
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    read-file-http https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md | file /src/myfile | contents
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      read-file-http --url=https://raw.githubusercontent.com/dagger/dagger/refs/heads/main/README.md \
      file --path=/src/myfile \
      contents
    ```
    </TabItem>
    </Tabs>

### Copy a file to the Dagger module runtime container for custom processing

The following Dagger Function accepts a `File` argument and copies the specified file to the Dagger module runtime container. This makes it possible to add one or more files to the runtime container and manipulate them using custom logic.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-file-runtime/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-file-runtime/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-file-runtime/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Copy the `data.json` host file to the runtime container and process it:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-file ../data.json'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-file ../data.json
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-file --source=../data.json
    ```
    </TabItem>
    </Tabs>

### Copy a subset of a directory or remote repository to a container using pre-defined filters

The following Dagger Function accepts a `Directory` argument, which could reference either a directory from the local filesystem or a [remote Git repository](../api/arguments.mdx#remote-repositories). It copies the specified directory to the `/src` path in a container, using pre-defined filter patterns to exclude specified sub-directories and files, and returns the modified container.

:::note
When working with private Git repositories, ensure that [SSH authentication is properly configured](../api/remote-repositories.mdx#ssh-authentication) on your Dagger host.
:::

:::note
This is an example of [pre-call filtering](../api/fs-filters.mdx#pre-call-filtering) with [directory filters](../api/fs-filters.mdx).
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/copy-filter-dir-pre/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/copy-filter-dir-pre/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/copy-filter-dir-pre/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Copy the specified host directory to `/src` in the container, excluding everything except Markdown files, and return the modified container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory-with-exclusions ../docs'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory-with-exclusions ../docs
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call copy-directory-with-exclusions --source=../docs
    ```
    </TabItem>
    </Tabs>

- Copy the public `dagger/dagger` GitHub repository to `/src` in the container, excluding everything except Markdown files, and list the contents of the `/src` directory in the container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'copy-directory-with-exclusions https://github.com/dagger/dagger#main | directory /src | entries'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    copy-directory-with-exclusions https://github.com/dagger/dagger#main | directory /src | entries
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      copy-directory-with-exclusions --source=https://github.com/dagger/dagger#main \
      directory --path=/src \
      entries
    ```
    </TabItem>
    </Tabs>

### Set a module-wide default path

The following Dagger module uses a constructor to set a module-wide `Directory` argument and point it to a default path on the host. This eliminates the need to pass a common `Directory` argument individually to each Dagger Function in the module. If required, the default path can be overridden by specifying a different `Directory` value at call time.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/set-common-default-path/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/set-common-default-path/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/set-common-default-path/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/set-common-default-path/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Examples

- Call the Dagger Function without arguments. The default path (the current directory `.`) is used:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c foo
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    foo
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call foo
    ```
    </TabItem>
    </Tabs>

- Call the Dagger Function with a constructor argument. The specified directory (`/src/myapp`) is used:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'my-module --source $(host | directory /src/myapp) | foo'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    my-module --source $(host | directory /src/myapp) | foo
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call --source=/src/myapp foo
    ```
    </TabItem>
    </Tabs>

## Builds

### Perform a multi-stage build

The following Dagger Function performs a multi-stage build.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/multi-stage-build/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/multi-stage-build/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/multi-stage-build/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/builds/multi-stage-build/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Example

Perform a multi-stage build of the source code in the `golang/example/hello` repository and publish the resulting image:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/golang/example#master:hello'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/golang/example#master:hello
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --src="https://github.com/golang/example#master:hello"
    ```
    </TabItem>
    </Tabs>

### Perform a matrix build

The following Dagger Function performs a matrix build.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/matrix-build/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/matrix-build/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/matrix-build/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/builds/matrix-build/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Example

Perform a matrix build of the source code in the `golang/example/hello` repository and export build directory with go binaries for different operating systems and architectures.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/golang/example#master:hello | export /tmp/matrix-builds'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/golang/example#master:hello | export /tmp/matrix-builds
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      build --src="https://github.com/golang/example#master:hello" \
      export --path=/tmp/matrix-builds
    ```
    </TabItem>
    </Tabs>

Inspect the contents of the exported directory with `tree /tmp/matrix-builds`. The output should look like this:

```shell
/tmp/matrix-builds
└── build
    ├── darwin
    │   ├── amd64
    │   │   └── hello
    │   └── arm64
    │       └── hello
    └── linux
        ├── amd64
        │   └── hello
        └── arm64
            └── hello

8 directories, 4 files
```

### Build multi-arch image

The following Dagger Function builds a single image for different CPU architectures using native emulation.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/multi-arch/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/multi-arch/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/multi-arch/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build and publish a multi-platform image:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/golang/example#master:hello'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/golang/example#master:hello
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --src="https://github.com/golang/example#master:hello"
    ```
    </TabItem>
    </Tabs>

### Build multi-arch image with cross-compliation

The following Dagger Function builds a single image for different CPU architectures using cross-compilation.

:::info
This Dagger Function uses the `containerd` utility module. To run it locally
install the module first with `dagger install github.com/levlaz/daggerverse/containerd@v0.1.2`
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/multi-arch-cc/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/multi-arch-cc/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/multi-arch-cc/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build and publish a multi-platform image with cross compliation:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/golang/example#master:hello'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/golang/example#master:hello
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --src="https://github.com/golang/example#master:hello"
    ```
    </TabItem>
    </Tabs>

### Build image from Dockerfile

The following Dagger Function builds an image from a Dockerfile.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/dockerfile/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/dockerfile/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/dockerfile/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/builds/dockerfile/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Example
Build and publish an image from an existing Dockerfile

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/dockersamples/python-flask-redis'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/dockersamples/python-flask-redis
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --src="https://github.com/dockersamples/python-flask-redis"
    ```
    </TabItem>
    </Tabs>

### Build image from Dockerfile using different build context

The following function builds an image from a Dockerfile with a build context that is different than the current working directory.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/dockerfile-context/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/dockerfile-context/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/dockerfile-context/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build an image from the source code in `https://github.com/dockersamples/python-flask-redis` using the Dockerfile from a different build context, at `https://github.com/vimagick/dockerfiles#master:registry-cli/Dockerfile`:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build https://github.com/dockersamples/python-flask-redis https://github.com/vimagick/dockerfiles#master:registry-cli/Dockerfile'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build https://github.com/dockersamples/python-flask-redis https://github.com/vimagick/dockerfiles#master:registry-cli/Dockerfile
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call \
      build --src="https://github.com/dockersamples/python-flask-redis" \
        --dockerfile=https://github.com/vimagick/dockerfiles#master:registry-cli/Dockerfile
    ```
    </TabItem>
    </Tabs>

### Add OCI annotations to image

The following Dagger Function adds [OpenContainer Initiative (OCI) annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md) to an image.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/oci-annotations/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/oci-annotations/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/oci-annotations/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build and publish an image with OCI annotations:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c build
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build
    ```
    </TabItem>
    </Tabs>

### Add OCI labels to image

The following Dagger Function adds [OpenContainer Initiative (OCI) labels](https://github.com/opencontainers/image-spec/blob/main/config.md) to an image.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/oci-labels/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/oci-labels/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/oci-labels/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build and publish an image with OCI labels:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c build
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build
    ```
    </TabItem>
    </Tabs>

### Invalidate cache

The following function demonstrates how to invalidate the Dagger layer cache and force execution of subsequent workflow steps, by introducing a volatile time variable at a specific point in the Dagger workflow.

:::note
* This is a temporary workaround until cache invalidation support is officially added to Dagger.
* Changes in mounted cache volumes or secrets do not invalidate the Dagger layer cache.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/builds/cache/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/builds/cache/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/builds/cache/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/builds/cache/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Example

Print the date and time, invalidating the cache on each run. However, if the `CACHEBUSTER` environment variable is removed, the same value (the date and time on the first run) is printed on every run.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c build
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build
    ```
    </TabItem>
    </Tabs>

## Secrets

### Use secret variables

The following Dagger Function accepts a GitHub personal access token as a `Secret`, and uses the `Secret` to authorize a request to the GitHub API. The secret may be sourced from the host (via an environment variable, host file, or host command) or from an external secrets manager (1Password or Vault):

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/secret-variable/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/secret-variable/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/secret-variable/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Use a secret sourced from an environment variable:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-api env://GITHUB_API_TOKEN'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-api env://GITHUB_API_TOKEN
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-api --token=env://GITHUB_API_TOKEN
    ```
    </TabItem>
    </Tabs>

- Use a secret sourced from a file:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-api file://./github.txt'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-api file://./github.txt
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-api --token=file://./github.txt
    ```
    </TabItem>
    </Tabs>

- Use a secret sourced from a command:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-api cmd://"gh auth token"'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-api cmd://"gh auth token"
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-api --token=cmd://"gh auth token"
    ```
    </TabItem>
    </Tabs>

- Use a secret from 1Password:

  :::note
  If using a [1Password service account](https://developer.1password.com/docs/service-accounts/), ensure that the `OP_SERVICE_ACCOUNT_TOKEN` environment variable is set.

    ```shell
    export OP_SERVICE_ACCOUNT_TOKEN="mytoken"
    ```
  :::

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-api op://infra/github/credential'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-api op://infra/github/credential
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-api --token=op://infra/github/credential
    ```
    </TabItem>
    </Tabs>

- Use a secret from Vault:

  :::note
  Ensure that the `VAULT_ADDR` and either the `VAULT_TOKEN` or `VAULT_APPROLE_ROLE_ID` (for [Vault AppRole authentication](https://developer.hashicorp.com/vault/docs/auth/approle)) environment variables are set.

    ```shell
    export VAULT_ADDR="https://127.0.0.1:8200"
    export VAULT_TOKEN="gue55me7"
    export VAULT_APPROLE_ROLE_ID="roleid-xxx-yyy-zzz"
    ```
  :::

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-api vault://credentials.github'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-api vault://credentials.github
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-api --token=vault://credentials.github
    ```
    </TabItem>
    </Tabs>

### Mount files as secrets

The following Dagger Function accepts a GitHub hosts configuration file as a `Secret`, and mounts the file as a `Secret` to a container to authorize a request to GitHub.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/secret-file/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/secret-file/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/secret-file/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Use a mounted secret file:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'github-auth file://$HOME/.config/gh/hosts.yml'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    github-auth file://$HOME/.config/gh/hosts.yml
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call github-auth --gh-creds=file://$HOME/.config/gh/hosts.yml
    ```
    </TabItem>
    </Tabs>

### Use secret in Dockerfile build

The following code listing demonstrates how to inject a secret into a Dockerfile build. The secret is automatically mounted in the build container at `/run/secrets/SECRET-ID`.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/secret-dockerfile/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/secret-dockerfile/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/secret-dockerfile/typescript/index.ts
```

</TabItem>
</Tabs>

The sample Dockerfile below demonstrates the process of mounting the secret using a secret filesystem mount type and using it in the Dockerfile build process:

```shell
FROM alpine:3.17
RUN apk add curl
RUN --mount=type=secret,id=gh-secret \
    curl "https://api.github.com/repos/dagger/dagger/issues" \
        --header "Accept: application/vnd.github+json" \
        --header "Authorization: Bearer $(cat /run/secrets/gh-secret)"
```

#### Example

Build from a Dockerfile with a mounted secret from the host environment:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build . env://GITHUB_API_TOKEN'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build . env://GITHUB_API_TOKEN
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --source=. --secret=env://GITHUB_API_TOKEN
    ```
    </TabItem>
    </Tabs>

### Customize secret caching behavior

By default, the layer cache entries for operations that include a secret will be based on the plaintext value of the secret. Operations that include secrets with the same plaintext value may share cache entries, but if the plaintext differs then the operation will not share cache entries.

In some cases, users may desire that operations share the layer cache entries even if the secret plaintext value is different. For example, a secret may often rotate in plaintext value but not be meaningfully different; in these cases, it should still be possible to reuse the cache for operations that include that secret.

For these use cases, the optional `cacheKey` argument to `Secret` construction can be used to specify the "cache key" of the secret. Secrets that share the same `cacheKey` will be considered equivalent when checking the layer cache for operations that include them, even if their plaintext value differs.

#### Example

Use a secret with a specified cache key:

<Tabs groupId="shell">
<TabItem value="System shell">
```shell
dagger -c 'github-api $(secret env://GITHUB_API_TOKEN --cache-key my-cache-key)'
```
</TabItem>
<TabItem value="Dagger Shell">
```shell title="First type 'dagger' for interactive mode."
github-api $(secret env://GITHUB_API_TOKEN --cache-key my-cache-key)
```
</TabItem>
<TabItem value="Dagger CLI">
```shell
dagger call github-api --token=env://GITHUB_API_TOKEN?cacheKey=my-cache-key
```
</TabItem>
</Tabs>

## Services

### Bind and use services in Dagger Functions

The first Dagger Function below creates and returns an HTTP service. This service is bound and used from a different Dagger Function, via a service binding using an alias like `www`.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/bind-services/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/bind-services/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/bind-services/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Send a request from one Dagger Function to a bound HTTP service instantiated by a different Dagger Function:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c get
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    get
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call get
    ```
    </TabItem>
    </Tabs>

### Expose services in Dagger Functions to the host

The Dagger Function below creates and returns an HTTP service. This service can be used from the host.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/expose-dagger-services-to-host/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/expose-dagger-services-to-host/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/expose-dagger-services-to-host/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Expose the HTTP service instantiated by a Dagger Function to the host on the default port:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'http-service | up'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    http-service | up
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call http-service up
    ```
    </TabItem>
    </Tabs>

    Access the service from the host:

    ```shell
    curl localhost:8080
    ```

- Expose the HTTP service instantiated by a Dagger Function to the host on a different host port:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'http-service | up --ports 9000:8080'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    http-service | up --ports 9000:8080
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call http-service up --ports 9000:8080
    ```
    </TabItem>
    </Tabs>

    Access the service from the host:

    ```shell
    curl localhost:9000
    ```

### Expose host services to Dagger Functions

The following Dagger Function accepts a `Service` running on the host, binds it using an alias, and creates a client to access it via the service binding. This example uses a MariaDB database service running on host port 3306, aliased as `db` in the Dagger Function.

:::note
This implies that a service is already listening on a port on the host, out-of-band of Dagger.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/expose-host-services-to-dagger/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/expose-host-services-to-dagger/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/expose-host-services-to-dagger/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Send a query to the database service listening on host port 3306 and return the result as a string:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'user-list tcp://localhost:3306'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    user-list tcp://localhost:3306
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call user-list --svc=tcp://localhost:3306
    ```
    </TabItem>
    </Tabs>

### Use service endpoints

The following Dagger Function starts a service manually, then retrieves its endpoint and sends a request. This example uses a NGINX HTTP service running on host port 80.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/use-endpoint/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/use-endpoint/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/use-endpoint/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Send a query to the HTTP service listening on host port 80 and return the result as a string:

<Tabs groupId="shell">
<TabItem value="System shell">
```shell
dagger -c get
```
</TabItem>
<TabItem value="Dagger Shell">
```shell title="First type 'dagger' for interactive mode."
get
```
</TabItem>
<TabItem value="Dagger CLI">
```shell
dagger call get
```
</TabItem>
</Tabs>

### Create a transient service for unit tests

The following Dagger Function creates a service and binds it to an application container for unit testing. In this example, the application being tested is Drupal. Drupal includes a large number of unit tests, including tests which depend on an active database service. This database service is created on-the-fly by the Dagger Function.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/test-against-db-service/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/test-against-db-service/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/test-against-db-service/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Run Drupal's unit tests, instantiating a database service during the process:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c test
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    test
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call test
    ```
    </TabItem>
    </Tabs>

### Start and stop services

The following Dagger Function demonstrates how to control a service's lifecycle by explicitly starting and stopping a service. This example uses a Redis service.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/start-stop-services/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/start-stop-services/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/start-stop-services/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Start and stop a Redis service:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c redis-service
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    redis-service
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call redis-service
    ```
    </TabItem>
    </Tabs>

### Create interdependent services

The following Dagger Function runs two services, service A and service B, that depend on each other. The services are set up with custom hostnames, `svca` and `svcb`, allowing each service to communicate with the other by hostname.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/create-interdependent-services/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/create-interdependent-services/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/create-interdependent-services/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Start two inter-dependent services:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'services | up --ports 8080:80'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    services | up --ports 8080:80
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call services up --ports 8080:80
    ```
    </TabItem>
    </Tabs>

## Just-in-time artifacts

### Publish a container image to a private registry

The following Dagger Function publishes a just-in-time container image to a private registry.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/publish-image/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/publish-image/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/publish-image/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Publish a just-in-time container image to Docker Hub, using the account username `user` and the password set in the `PASSWORD` environment variable:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'publish docker.io user env://PASSWORD'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    publish docker.io user env://PASSWORD
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call publish --registry=docker.io --username=user --password=env://PASSWORD
    ```
    </TabItem>
    </Tabs>

- Publish a just-in-time container image to GitHub Container Registry, using the account username `user` and the GitHub personal access token set in the `PASSWORD` environment variable:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'publish gchr.io user env://PASSWORD'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    publish gchr.io user env://PASSWORD
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call publish --registry=gchr.io --username=user --password=env://PASSWORD
    ```
    </TabItem>
    </Tabs>

### Publish a container image to a private registry with multiple tags

The following Dagger Function tags a just-in-time container image multiple times and publishes it to a private registry.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/tag-publish-image/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/tag-publish-image/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/tag-publish-image/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Tag and publish a just-in-time container image to Docker Hub, using the account username `user` and the password set in the `PASSWORD` environment variable:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'publish docker.io user env://PASSWORD'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    publish docker.io user env://PASSWORD
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call publish --registry=docker.io --username=user --password=env://PASSWORD
    ```
    </TabItem>
    </Tabs>

- Tag and publish a just-in-time container image to GitHub Container Registry, using the account username `user` and the GitHub personal access token set in the `PASSWORD` environment variable:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'publish gchr.io user env://PASSWORD'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    publish gchr.io user env://PASSWORD
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call publish --registry=gchr.io --username=user --password=env://PASSWORD
    ```
    </TabItem>
    </Tabs>

### Build and load a container image into the host Docker Engine

The following Dagger Function builds a just-in-time container image and loads it into the Docker Engine running on the host.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/load-image-host/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/load-image-host/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/load-image-host/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Build and load a just-in-time container image into the Docker Engine running on the host:

<Tabs groupId="shell">
<TabItem value="System shell">
```shell
dagger -c 'load /var/run/docker.sock myimage'
```
</TabItem>
<TabItem value="Dagger Shell">
```shell title="First type 'dagger' for interactive mode."
load /var/run/docker.sock myimage
```
</TabItem>
<TabItem value="Dagger CLI">
```shell
dagger call load --docker=/var/run/docker.sock --tag=myimage
```
</TabItem>
</Tabs>

### Export a directory or file to the host

The following Dagger Functions return a just-in-time directory and file. These outputs can be exported to the host with `dagger call ... export ...`.

:::note
When a host directory or file is copied or mounted to a container's filesystem, modifications made to it in the container do not automatically transfer back to the host. Data flows only one way between Dagger operations, because they are connected in a DAG. To transfer modifications back to the local host, you must explicitly export the directory or file back to the host filesystem.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/export-file-dir/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/export-file-dir/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/export-file-dir/typescript/index.ts
```

</TabItem>
</Tabs>

#### Examples

- Export the directory returned by the Dagger Function to the `/home/admin/export` path on the host:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'get-dir | export /home/admin/export'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    get-dir | export /home/admin/export
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call get-dir export --path=/home/admin/export
    ```
    </TabItem>
    </Tabs>

- Export the file returned by the Dagger Function to the `/home/admin/myfile` path on the host:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'get-file | export /home/admin/myfile'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    get-file | export /home/admin/myfile
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call get-file export --path=/home/admin/myfile
    ```
    </TabItem>
    </Tabs>

### Export a container image to the host

The following Dagger Function returns a just-in-time container. This can be exported to the host as an OCI tarball.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/export-container/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/export-container/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/export-container/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Export the container image returned by the Dagger Function as an OCI tarball to the `/home/admin/mycontainer.tgz` path on the host. This OCI tarball can then be loaded into Docker with `docker load ...`.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'base | export /home/admin/mycontainer.tgz'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    base | export /home/admin/mycontainer.tgz
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call base export --path=/home/admin/mycontainer.tgz
    ```
    </TabItem>
    </Tabs>

## Optimizations

### Cache application dependencies

The following Dagger Function uses a cache volume for application dependencies. This enables Dagger to reuse the contents of the cache across Dagger Function runs and reduce execution time.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/cache-dependencies/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

:::note
The default location for the cache directory depends on the package manager (`~/.cache/pip` for `pip` or `~/.cache/pypoetry` for `poetry`).
:::

```python file=./snippets/cache-dependencies/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/cache-dependencies/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/cache-dependencies/php/src/MyModule.php
```

</TabItem>
</Tabs>

#### Example

Build an application using cached dependencies:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'build .'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    build .
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call build --source=.
    ```
    </TabItem>
    </Tabs>

### Set environment variables in a container

The following Dagger Function demonstrates how to set a single environment variable in a container.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/set-env-var/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/set-env-var/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/set-env-var/typescript/index.ts
```

</TabItem>
<TabItem value="php" label="PHP">

```php file=./snippets/set-env-var/php/src/MyModule.php
```

</TabItem>
</Tabs>

The following Dagger Function demonstrates how to set multiple environment variables in a container.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/set-env-vars/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/set-env-vars/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/set-env-vars/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

- Set a single environment variable in a container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c set-env-var
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    set-env-var
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call set-env-var
    ```
    </TabItem>
    </Tabs>

- Set multiple environment variables in a container:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c set-env-vars
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    set-env-vars
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call set-env-vars
    ```
    </TabItem>
    </Tabs>

### Persist service state across runs

The following Dagger Function uses a cache volume to persist a Redis service's data across Dagger Function runs.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/services/persist-service-state/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=../api/snippets/services/persist-service-state/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/services/persist-service-state/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

- Save data to a Redis service which uses a cache volume to persist a key named `foo` with value `123:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'set foo 123'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    set foo 123
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call set --key=foo --value=123
    ```
    </TabItem>
    </Tabs>

- Retrieve the value of the key `foo` after recreating the service state from the cache volume:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'get foo'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    get foo
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call get --key=foo
    ```
    </TabItem>
    </Tabs>

### Execute functions concurrently

The following Dagger Function demonstrates how to use native-language concurrency features ([errgroups](https://pkg.go.dev/golang.org/x/sync/errgroup) in Go, [task groups](https://anyio.readthedocs.io/en/stable/tasks.html) in Python), and [promises](https://basarat.gitbook.io/typescript/future-javascript/promise) in TypeScript to execute other Dagger Functions concurrently. If any of the concurrently-running functions fails, the remaining ones will be immediately cancelled.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/execute-concurrently/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/execute-concurrently/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/execute-concurrently/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Execute a Dagger Function which performs different types of tests by executing other Dagger Functions concurrently.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'my-module $(host | directory .) | run-all-tests'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    my-module $(host | directory .) | run-all-tests
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call --source=. run-all-tests
    ```
    </TabItem>
    </Tabs>

## Error handling

### Terminate gracefully

The following Dagger Function demonstrates how to handle errors in a workflow.


<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/handle-errors/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/handle-errors/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/handle-errors/typescript/index.ts
```

</TabItem>
</Tabs>

#### Example

Execute a Dagger Function which creates a container and runs a command in it. If the command fails, the error is captured and the Dagger Function is gracefully terminated with a custom error message.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c test
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    test
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call test
    ```
    </TabItem>
    </Tabs>

### Continue using a container after command execution fails

The following Dagger Function demonstrates how to continue using a container after a command executed within it fails. A common use case for this is to export a report that a test suite tool generates.

:::note
The caveat with this approach is that forcing a zero exit code on a failure caches the failure. This may not be desired depending on the use case.
:::

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=./snippets/continue-after-errors/go/main.go
```

</TabItem>
<TabItem value="python" label="Python">

```python file=./snippets/continue-after-errors/python/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=./snippets/continue-after-errors/typescript/src/index.ts
```

</TabItem>
</Tabs>

#### Example

Continue executing a Dagger Function even after a command within it fails. The Dagger Function returns a custom `TestResult` object containing a test report and the exit code of the failed command.

- Obtain the exit code:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'test | exit-code'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    test | exit-code
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call test exit-code
    ```
    </TabItem>
    </Tabs>

- Obtain the report:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c 'test | report | contents'
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    test | report | contents
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call test report contents
    ```
    </TabItem>
    </Tabs>

## Debugging

### Debug container builds

Dagger provides two features that can help greatly when trying to debug a workflow - opening an interactive terminal session at the failure point, or at explicit breakpoints throughout your workflow code. All context is available at the point of failure. Multiple terminals are supported in the same Dagger Function; they will open in sequence.

The following Dagger Function opens an interactive terminal session at different stages in a Dagger workflow to debug a container build.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/debugging/go/terminal-container/main.go
```

</TabItem>
<TabItem value="python" label="Python">
```python file=../api/snippets/debugging/python/terminal-container/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/debugging/typescript/terminal-container/index.ts
```

</TabItem>
</Tabs>

#### Example

Execute a Dagger Function to build a container, and open an interactive terminal at two different points in the build process. The interactive terminal enables you to inspect the container filesystem and environment "live", during the build process.

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c container
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    container
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call container
    ```
    </TabItem>
    </Tabs>

### Inspect directories and files

The following Dagger Function clones Dagger's GitHub repository and opens an interactive terminal session to inspect it. Under the hood, this creates a new container (defaults to `alpine`) and starts a shell, mounting the repository directory inside.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/debugging/go/terminal-directory-1/main.go
```

</TabItem>
<TabItem value="python" label="Python">
```python file=../api/snippets/debugging/python/terminal-directory-1/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/debugging/typescript/terminal-directory-1/index.ts
```

</TabItem>
</Tabs>

The container created to mount the directory can be customized using additional options. The following Dagger Function revised the previous example to demonstrate this, using an `ubuntu` container image and `bash` shell instead of the defaults.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">

```go file=../api/snippets/debugging/go/terminal-directory-2/main.go
```

</TabItem>
<TabItem value="python" label="Python">
```python file=../api/snippets/debugging/python/terminal-directory-2/main.py
```

</TabItem>
<TabItem value="typescript" label="TypeScript">

```typescript file=../api/snippets/debugging/typescript/terminal-directory-2/index.ts
```

</TabItem>
</Tabs>

#### Example

- Execute a Dagger Function to clone Dagger's GitHub repository and open a terminal session in the repository directory:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c simple-directory
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    simple-directory
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call simple-directory
    ```
    </TabItem>
    </Tabs>

- Execute another Dagger Function that does the same as the previous one, except using an `ubuntu` container image as base and initializing the terminal with the `bash` shell:

    <Tabs groupId="shell">
    <TabItem value="System shell">
    ```shell
    dagger -c advanced-directory
    ```
    </TabItem>
    <TabItem value="Dagger Shell">
    ```shell title="First type 'dagger' for interactive mode."
    advanced-directory
    ```
    </TabItem>
    <TabItem value="Dagger CLI">
    ```shell
    dagger call advanced-directory
    ```
    </TabItem>
    </Tabs>

### Create custom spans

Dagger represents operations performed by a Dagger Function as [OpenTelemetry spans](https://opentelemetry.io/docs/concepts/signals/traces/#spans). Spans are typically used to separate tasks that are running in parallel, with each branch waiting for completion.

It is possible to instrument custom OpenTelemetry spans inside any Dagger Function. This allows you to define logical boundaries within complex workflows, measure execution time, and track nested operations with greater granularity. These custom spans appear in the Dagger TUI and Traces.

The following Dagger Function demonstrates this by emitting custom spans for various tasks.

:::warning
The approach described below is experimental and may be deprecated in favor of a new OpenTelemetry span API. [Contribute to the ongoing discussion of this topic on GitHub](https://github.com/dagger/dagger/pull/9327).
:::

<Tabs groupId="language">
<TabItem value="Go">

```go file=./snippets/custom-spans/go/main.go
```

</TabItem>
<TabItem value="Python">
```python file=./snippets/custom-spans/python/main.py
```

</TabItem>
<TabItem value="TypeScript">

```typescript file=./snippets/custom-spans/typescript/index.ts
```

</TabItem>
</Tabs>

:::warning
When using spans to group and measure Dagger API function calls, ensure that the function calls are not [lazily evaluated](../api/internals.mdx#lazy-evaluation). The duration of the corresponding spans in this case will always be zero.
:::

#### Example

Execute a Dagger Function to run unit tests on the `dagger/hello-dagger` source code repository with different versions of Node.js, emitting a custom span for each version tested:

```shell
dagger call foo
```
